package com.safeluck.floatwindow;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceView;

import com.alivc.live.pusher.AlivcAudioAACProfileEnum;
import com.alivc.live.pusher.AlivcAudioChannelEnum;
import com.alivc.live.pusher.AlivcAudioSampleRateEnum;
import com.alivc.live.pusher.AlivcEncodeModeEnum;
import com.alivc.live.pusher.AlivcFpsEnum;
import com.alivc.live.pusher.AlivcImageFormat;
import com.alivc.live.pusher.AlivcLivePushCameraTypeEnum;
import com.alivc.live.pusher.AlivcLivePushConfig;
import com.alivc.live.pusher.AlivcLivePushError;
import com.alivc.live.pusher.AlivcLivePushErrorListener;
import com.alivc.live.pusher.AlivcLivePushInfoListener;
import com.alivc.live.pusher.AlivcLivePushNetworkListener;
import com.alivc.live.pusher.AlivcLivePushStats;
import com.alivc.live.pusher.AlivcLivePusher;
import com.alivc.live.pusher.AlivcPreviewOrientationEnum;
import com.alivc.live.pusher.AlivcQualityModeEnum;
import com.alivc.live.pusher.AlivcResolutionEnum;
import com.anyun.libusbcamera.UsbCamera;
import com.orhanobut.logger.Logger;
import com.safeluck.floatwindow.util.MyLog;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * aaa
 * Created by lzw on 2018/9/27. 14:09:18
 * 邮箱：632393724@qq.com
 * All Rights Saved! Chongqing AnYun Tech co. LTD
 */
public class  AliSdkMgr {

    private static final String TAG = "AliSdkMgr";
    private volatile static AliSdkMgr mInstance = null;
    private AlivcLivePusher mAlivcPusher;
    private UICallBackListener mUICallbackListener;
    private AlivcLivePushConfig mAlivcLivePushConfig;
    private Size size;//推流使用的分辨率
    private Context context;
    private String  mPushUrl = "rtmp://video-center-bj.alivecdn.com/AppName/StreamName?vhost=live.aaej.cn";
    private int onPreviewCount = 0;//标记阿里推流onPreview回调的次数，超过三次，则默认为推流失败，
    //usbCamera是否存在

    private boolean cameraExists;
    private UsbCamera usbCamera ;
    private MediaArgu mediaArgu;
    private boolean videoThreadOn;
    private boolean ay_encrypt = false;//是否开启摄像头加密

    public void setUIListener(UICallBackListener uiListener){
        this.mUICallbackListener = uiListener;
    }

    private AliSdkMgr(Context context){
        mAlivcLivePushConfig = new AlivcLivePushConfig();//初始化推流配置类
        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_240P);//分辨率540P，最大支持720P
        mAlivcLivePushConfig.setFps(AlivcFpsEnum.FPS_20); //建议用户使用20fps
        mAlivcLivePushConfig.setEnableBitrateControl(true); // 打开码率自适应，默认为true
        mAlivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_PORTRAIT); // 默认为竖屏，可设置home键向左或向右横屏。
        mAlivcLivePushConfig.setAudioProfile(AlivcAudioAACProfileEnum.AAC_LC);//设置音频编码模式
        mAlivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK);
        mAlivcLivePushConfig.setVideoEncodeMode(AlivcEncodeModeEnum.Encode_MODE_HARD);
        mAlivcLivePushConfig.setEnableBitrateControl(true);// 打开码率自适应，默认为true
        mAlivcLivePushConfig.setExternMainStream(false);// 设置自定义流模式
        mAlivcLivePushConfig.setBeautyOn(false); //关闭美颜
        mAlivcLivePushConfig.setPreviewOrientation(AlivcPreviewOrientationEnum.ORIENTATION_LANDSCAPE_HOME_LEFT);
        this.context = context;
        //QM_RESOLUTION_FIRST 清晰度优先模式。SDK内部会对码率参数进行配置，优先保障推流视频的清晰度。
        mAlivcLivePushConfig.setQualityMode(AlivcQualityModeEnum.QM_RESOLUTION_FIRST);


    }
    public void initSdk(){
        final Handler handler = new Handler(Looper.getMainLooper());
        mAlivcPusher = new AlivcLivePusher();
        if (mediaArgu != null){
            if (!TextUtils.isEmpty(mediaArgu.getUrl())){
                Logger.i("修改直播地址"+mediaArgu.getUrl());
                mPushUrl = mediaArgu.getUrl();
            }
        }
        if (mediaArgu!= null && mediaArgu.isUsedOutCamera()){

            if (usbCamera ==null){
                Log.i(TAG, "initSdk: 需要外设USBCamera new一个");
                usbCamera = new UsbCamera();
            }
            if (mAlivcLivePushConfig !=null){
                Log.i(TAG, "initSdk: 需要阿里自定义流");
                mAlivcLivePushConfig.setExternMainStream(true);
                mAlivcLivePushConfig.setAlivcExternMainImageFormat(AlivcImageFormat.IMAGE_FORMAT_YUV420P);

            }
        }else{
            for (int a :
                    arr) {
                Log.i(TAG, "initSdk: 内置摄像头重设分辨率" +a);
                switch (a){
                    case 180:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_180P);
                        break;
                        case 240:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_240P);
                        break;
                        case 360:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_360P);
                        break;
                        case 480:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_480P);
                        break;           case 540:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_540P);
                        break;           case 720:
                        mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_720P);
                        break;
                }
            }

        }

        mAlivcPusher.init(context.getApplicationContext(),mAlivcLivePushConfig);

        mAlivcPusher.setLivePushInfoListener(new AlivcLivePushInfoListener() {
            @Override
            public void onPreviewStarted(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPreviewStarted: ");
                if (onPreviewCount == 3){
                    if (mUICallbackListener != null){
                        MyLog.i(TAG, "onPreviewStarted:出现三次，回调失败 ");
                        mUICallbackListener.onConnectFail();
                    }
                }
                onPreviewCount++;
                if (mUICallbackListener != null){
                    mUICallbackListener.rtmpAddr(mPushUrl);
                }

                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mAlivcPusher!=null &&mAlivcPusher.getCurrentStatus() != AlivcLivePushStats.PREVIEWED && mAlivcPusher.getCurrentStatus()!= AlivcLivePushStats.PUSHED){
                            MyLog.i(TAG, "run: OnPreviee抛异常");
                        }else{

                            if (mediaArgu.isUsedOutCamera() && !cameraExists){
                                MyLog.i(TAG, "run: 不进行推流，usbCamera不存在");
                            }else{
                                MyLog.i(TAG,"call AlivcPusher.startPushAsync"+mPushUrl);
                                mAlivcPusher.startPushAysnc(mPushUrl);
                            }

                        }
                    }
                },1000);

            }

            @Override
            public void onPreviewStoped(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPreviewStoped: ");
            }

            @Override
            public void onPushStarted(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPushStarted: ");
                if (mUICallbackListener != null){
                    if (mediaArgu.isUsedOutCamera()){

                        mUICallbackListener.onPushStarted(arr[0],arr[1]);
                    }else{
                        MyLog.i(TAG,"内部设备摄像头分辨率"+arr[0]+arr[1]);
                        mUICallbackListener.onPushStarted(arr[0],arr[1]);
                    }
                }

            }

            @Override
            public void onPushPauesed(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPushPauesed: ");
            }

            @Override
            public void onPushResumed(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPushResumed: ");
            }

            @Override
            public void onPushStoped(AlivcLivePusher alivcLivePusher) {
                Log.i(TAG, "onPushStoped: ");
                if (mediaArgu.isUsedOutCamera()){
                }

                if(mUICallbackListener != null){
                    mUICallbackListener.onPushStoped(4);
                }
            }

            @Override
            public void onPushRestarted(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPushRestarted: ");
            }

            @Override
            public void onFirstFramePreviewed(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onFirstFramePreviewed: ");
            }

            @Override
            public void onDropFrame(AlivcLivePusher alivcLivePusher, int i, int i1) {

            }

            @Override
            public void onAdjustBitRate(AlivcLivePusher alivcLivePusher, int i, int i1) {

            }

            @Override
            public void onAdjustFps(AlivcLivePusher alivcLivePusher, int i, int i1) {

            }
        });


        mAlivcPusher.setLivePushErrorListener(new AlivcLivePushErrorListener() {
            @Override
            public void onSystemError(AlivcLivePusher alivcLivePusher, AlivcLivePushError alivcLivePushError) {
                Log.i(TAG, "onSystemError: "+alivcLivePushError.toString());
                //当出现onSystemError系统级错误时，您需要退出直播。

                alivcLivePusher.stopPush();

            }

            @Override
            public void onSDKError(AlivcLivePusher alivcLivePusher, AlivcLivePushError alivcLivePushError) {
                Log.i(TAG, "onSDKError: "+alivcLivePushError.toString());
//                当出现onSDKError错误（SDK错误）时，有两种处理方式，选择其一即可：销毁当前直播，重新创建或调用restartPush/restartPushAsync重启AlivcLivePusher。
                alivcLivePusher.restartPushAync();
            }
        });

        mAlivcPusher.setLivePushNetworkListener(new AlivcLivePushNetworkListener() {
            @Override
            public void onNetworkPoor(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onNetworkPoor: ");
                if (mUICallbackListener != null){
                    mUICallbackListener.onNetworkPoor();
                }
            }

            @Override
            public void onNetworkRecovery(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onNetworkRecovery: ");
            }

            @Override
            public void onReconnectStart(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onReconnectStart: "+mPushUrl);
//                alivcLivePusher.reconnectPushAsync(mPushUrl);
            }

            @Override
            public void onReconnectFail(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onReconnectFail: ");
                if (mUICallbackListener !=null){
                    mUICallbackListener.onReconnectFail();
                }
            }

            @Override
            public void onReconnectSucceed(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onReconnectSucceed: ");
            }

            @Override
            public void onSendDataTimeout(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onSendDataTimeout: ");
            }

            @Override
            public void onConnectFail(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onConnectFail: ");
                if (mUICallbackListener != null){
                    mUICallbackListener.onConnectFail();
                }
            }

            @Override
            public String onPushURLAuthenticationOverdue(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onPushURLAuthenticationOverdue: ");
                return null;
            }

            @Override
            public void onSendMessage(AlivcLivePusher alivcLivePusher) {
                MyLog.i(TAG, "onSendMessage: ");
            }
        });




    }
    public static AliSdkMgr getInstance(Context context){
        if (mInstance == null){
            synchronized (AliSdkMgr.class){
                if (mInstance == null){
                    mInstance = new AliSdkMgr(context);
                }
            }
        }
        return mInstance;
    }

    public UsbCamera
    getUsbCamera() {
        return usbCamera;
    }



    public void transferMediaArgu(MediaArgu mediaArgu){
        this.mediaArgu = mediaArgu;
        MyLog.i(TAG, "transferMediaArgu: ");
        arr[0] = mediaArgu.getM_screen().width;
        arr[1] = mediaArgu.getM_screen().height;
        MyLog.i(TAG, "mAlivcLivePushConfig 重设分辨率" +arr[0]+"*"+arr[1]);
        for (int a :
                arr) {

            switch (a){
                case 180:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_180P);
                    break;
                case 240:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_240P);
                    break;
                case 360:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_360P);
                    break;
                case 480:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_480P);
                    break;           case 540:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_540P);
                    break;           case 720:
                    mAlivcLivePushConfig.setResolution(AlivcResolutionEnum.RESOLUTION_720P);
                    break;
            }
        }

    }
    //设置码率 帧率 分辨率 推流地址

    public void setOutConfigure(int codeRate, int frameRate, int screenRate,String url){
        //        在配置好推流参数后，可以使用推流SDK的init方法进行初始化
        this.mPushUrl = url;
        //AlivcLivePusher目前不支持多实例，所以一个init必须对应有一个destory。  alivcLivePusher.destroy();

    }
public boolean checkUsbCameraExist(){
    ExecutorService executorService = Executors.newCachedThreadPool();
    Future<Integer> retF = executorService.submit(checkCamera);
    try {
        if (retF.get() == -1){
            return false;
        }else{
            return true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
public boolean openUsbCameraExist(){
    ExecutorService executorService = Executors.newCachedThreadPool();
    Future<Integer> retF = executorService.submit(openCamera);
    try {
        if (retF.get() == -1){
            return false;
        }else{
            return true;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}
    public void startPreviewAsync(SurfaceView surfaceView){
        if (mAlivcPusher != null){

            if (mediaArgu.isUsedOutCamera()){


                    if (!openUsbCameraExist()){
                        cameraExists = false;
                        if (mUICallbackListener !=null){

                            mUICallbackListener.onPushStoped(-1);
                        }
                    }else{

                        cameraExists = true;
                        MyLog.i(TAG, "startPreviewAsync: usbCamera打开");

                        mAlivcPusher.startPreviewAysnc(surfaceView);
                        startYUV(context);
                    }


            }else{
                mAlivcPusher.startPreviewAysnc(surfaceView);
            }


            MyLog.i(TAG, "startPreviewAsync: ");


        }
    }

    /**推流
     * 事先检查usbCamera存在否 使用完usbcamera=null;
     * 因为在initSdk()开始推流的时候有打开usbcamera
     */
    public Callable<Integer> checkCamera = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            if (usbCamera == null){
                usbCamera = new UsbCamera();
                usbCamera.setenv();
                int ret = usbCamera.prepareCameraWithBase(0,0,arr,ay_encrypt);
                usbCamera.stopCamera();
                usbCamera = null;
                return ret;
            }else{
                int ret = usbCamera.prepareCameraWithBase(0,0,arr,ay_encrypt);
                usbCamera.stopCamera();
                usbCamera = null;
                return ret;
            }


        }
    };
    public Callable<Integer> openCamera = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {


            int ret = usbCamera.prepareCameraWithBase( 0, 0 ,arr,ay_encrypt);
            MyLog.i(TAG, "call: UsbCamera推流分辨率"+arr[0]+"X"+arr[1]);

            return ret;
        }
    };
private int[] arr =new int[]{640,480};
    public void startYUV(final Context context) {
        if (mediaArgu.isUsedOutCamera()){
            if (mediaArgu.isPush()){

        }

        }

        new Thread(new Runnable() {
            @Override
            public void run() {
//                int ret = usbCamera.prepareCameraWithBase( 0, 0 ,arr);
//                if (ret != -1) {
//                    cameraExists = true;
//                    Log.d(TAG, "usb cameraExists");
//                }else{
//                    Log.d(TAG, "run: usbCamera not exist");
//                    if (mUICallbackListener != null){
//                        Log.i(TAG, "run: 外部摄像头不存在");
//                        mUICallbackListener.onPushStoped(-1);
//                        cameraExists = false;
//                        return;
//                    }
//                }
//
//                try {
//                    Thread.sleep(1000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }

                {
                    //发数据
                    while(cameraExists)
                    {
                        if (usbCamera.processCamera() == -1){
                            cameraExists = false;
                            if (mUICallbackListener != null){
                                MyLog.i(TAG, "run: 外部摄像头不存在");
                                mUICallbackListener.onPushStoped(-1);


                            }
                            break;
                        }
                        byte[] buffer = new byte[640*480*3/2];

                        //1-推流 0-录像
                        if (mediaArgu.isPush()){
                            usbCamera.rgba(1,buffer);
                        }else{
                            usbCamera.rgba(0,buffer);
                        }




                        mAlivcPusher.inputStreamVideoData(buffer,arr[0],arr[1], buffer.length,System.nanoTime()/1000,0);

                    }
                }
            }
        }).start();
    }










    public void destroyAliSdk(){
        if (mAlivcPusher != null){

        AlivcLivePushStats alivcLivePushStats = mAlivcPusher.getCurrentStatus();
 
            MyLog.i(TAG, "destroyAliSdk: stats="+alivcLivePushStats.name());
            onPreviewCount = 0;
                if (mUICallbackListener != null){
                    mUICallbackListener.onPushStoped(4);
                }
                mAlivcPusher.destroy();

            mAlivcPusher = null;
            mUICallbackListener = null;
            if (mediaArgu.isPush()&&usbCamera != null){
                MyLog.i(TAG, "destroyAliSdk: 推流结束,停用外部USBCamera");
                usbCamera.stopCamera();
            }
        }
    }
}
